#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Author: lonewolf
# Date: 2013-09-25 09:58:52
#
import re
import os
import shutil
import json
import time

lufylegend_root="/Users/lonewolf/Public/dev/web/html5/res/lufylegend.js-lufylegend-1.9.7/src/"
srcPath = [lufylegend_root]

# snippet模板
snippetTemplate = """<snippet>
    <content><![CDATA[$content]]></content>
    <tabTrigger>$trigger</tabTrigger>
    <scope>source.js</scope>
    <description>$desc</description>
</snippet>
"""
# 定义信息文件模板
definitionTemplate="""#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Author: lonewolf
# Date: $datetime
#
data=\"\"\"$json\"\"\"
"""
# 定义信息列表
# 项：item[key,path,"",lineNum]
definitionList=[]

# 保存的目录
SAVE_DIR="lufylegend_api"

# 解析各个目录或文件
def parse(paths):
    # 建立目录
    saveDir=SAVE_DIR
    for path in paths:
        parseDir(path,saveDir)

def parseDir(dir,saveDir):
    for item in os.listdir(dir):
        path=os.path.join(dir,item)
        if os.path.isdir(path):
            dirname=item
            childDir=os.path.join(saveDir,dirname)
            parseDir(path,childDir)
        elif os.path.isfile(path):
            ext=os.path.splitext(item)[1][1:]
            if ext=="js":
                parseJs(path,saveDir)

# 解析js文件
def parseJs(file,saveDir):
    completionsList=[]
    filename=os.path.split(file)[1]
    filename=os.path.splitext(filename)[0]
    f=open(file,"r")
    lineNum=0
    # 类名
    classname=""
    # 静态类
    isStaticMethod=False
    isStaticProp=False
    prop=""
    while True:
        line=f.readline()
        if line:
            lineNum+=1
            #特殊处理文件
            if filename=="LTweenLite":
                m=re.match("^\s*(\w+)\s*:\s*function\s*\((.*)\)\s*\{",line)
                if m:
                    classname="LTweenLite"
                    funcName=m.group(1)
                    if ["to","remove","removeAll"].count(funcName)>0:
                        funcName=classname+"."+funcName
                        handleDefinition(funcName,file,lineNum)
                        handleFunction(saveDir,classname,funcName,m.group(2))
                continue
            if filename=="Function":
                m=re.match("^function\s+(\w+)\s*\((.*)\)\s*\{",line)
                if m:
                    classname="Function"
                    funcName=m.group(1)
                    handleDefinition(funcName,file,lineNum)
                    handleFunction(saveDir,classname,funcName,m.group(2))
                continue
            if filename=="LConstant":
                m=re.match("^var\s+(\w+)\s*=\s*",line)
                m2=re.match("^(\w+)\s*=\s*",line)
                if m2:
                    m=m2
                if m:
                    classname="LConstant"
                    propName=m.group(1)
                    handleDefinition(propName,file,lineNum)
                    handleProp(saveDir,classname,propName)
                continue
            # 单例类
            m=re.match("^function\s+(\w+)\s*\(\)\s*\{throw",line)
            m2=re.match("^var\s+(\w+)\s*=\s*function\s*\(\)\s*\{throw",line)
            if m2:
                m=m2
            if m:
                classname=m.group(1)
                handleDefinition(classname,file,lineNum)
                continue
            # 类名
            m=re.match("^function\s+(\w+)\s*\(\)\s*\{",line)
            m2=re.match("^var\s+(\w+)\s*=\s*\(\s*function\s*\(\)\s*\{",line)
            if m2:
                m=m2
            if m:
                classname=m.group(1)
                # if classname=="LGlobal":
                #     print(m.group(1))
                continue
            m=re.match("^function\s+(\w+)\s*\((.*)\)\s*\{",line)
            if m:
                classname=m.group(1)
                handleDefinition(classname,file,lineNum)
                handleFunction(saveDir,classname,classname,m.group(2))
                continue

            if classname=="":
                continue
            # 构造
            m=re.match("^\s+function\s+%s\s*\((.*)\)\s*\{"%(classname),line)
            if m:
                handleDefinition(classname,file,lineNum)
                handleFunction(saveDir,classname,classname,m.group(1))
                continue
            # 静态方法
            m=re.match("^\s\**Static method",line)
            if m:
                isStaticMethod=True
                continue
            m=re.match("^\s*%s\.(\w+)\s*=\s*function\s*\((.*)\)\s*\{"%(classname),line)
            if m:
                funcName=classname+"."+m.group(1)
                handleDefinition(funcName,file,lineNum)
                handleFunction(saveDir,classname,funcName,m.group(2))
                continue
            # 普通方法
            m=re.match("^\s*var\s+p\s*=\s*\{",line)
            m2=re.match("^\s*%s\.prototype\s*=\s*\{",line)
            if m or m2:
                isStaticMethod=False
                continue
            m=re.match("^\s*(\w+)\.prototype\.(\w+)\s*=\s*function\s*\((.*)\)\s*\{",line)
            if m:
                handleDefinition(m.group(2),file,lineNum)
                handleFunction(saveDir,m.group(1),m.group(2),m.group(3))
                continue
            m=re.match("^\s*(\w+)\s*:\s*function\s*\((.*)\)\s*\{",line)
            if m:
                funcName=m.group(1)
                if isStaticMethod:
                    funcName=classname+"."+funcName
                    isStaticMethod=False
                handleDefinition(funcName,file,lineNum)
                handleFunction(saveDir,classname,funcName,m.group(2))
                continue
            # 静态变量
            m=re.match("^\s*\*.*\[static\]",line)
            m2=re.match("^\s*\*.*\[静态\]",line)
            m3=re.match("^\s*\*\s*\@static",line)
            if m or m2 or m3:
                isStaticProp=True
                continue
            m=re.match("^\s*%s\.(\w+)\s*="%(classname),line)
            if m:
                isStaticProp=False
                # if classname=="LGlobal":
                #     print(m.group(1))
                propName=classname+"."+m.group(1)
                handleDefinition(propName,file,lineNum)
                handleProp(saveDir,classname,propName)
                continue
            # 普通变量
            m=re.match("^\s*\*\s+@property\s+(\w+)",line)
            if m:
                prop=m.group(1)
                continue
            m=re.match("^\s*s\.%s\s*="%(prop),line)
            pp=""
            if prop and m:
                pp=prop
            m2=re.match("^\s*this\.(\w+)\s*=",line)
            if m2:
                pp=m2.group(1)
            if pp:
                propName=pp
                prop=""
                if isStaticProp:
                    propName=classname+"."+propName
                    isStaticProp=False
                handleDefinition(propName,file,lineNum)
                handleProp(saveDir,classname,propName)
                continue
        else:
            break
    f.close()

# 处理定义处，路径相对于lufylegend_root
def handleDefinition(keyword,filePath,lineNum):
    path=filePath[len(lufylegend_root):]
    dot=keyword.rfind(".")
    if dot!=-1:
        keyword2=keyword[(dot+1):]
        # print(keyword2)
        handleDefinition(keyword2,filePath,lineNum)
    definitionList.append([keyword,path,"",lineNum])

# 处理方法,生成snippet文件
def handleFunction(saveDir,classname,funcName,params,childClass=None):
    # 以_开头的不记录
    if funcName.find("_")!=-1:
        return
    arr=handleParams(params)
    content=funcName+"(%s)"%(arr[1])
    trigger=funcName+"(%s)"%(arr[0])
    template=snippetTemplate.replace("$content",content)
    template=template.replace("$trigger",trigger)
    if childClass:
        template=template.replace("$desc",childClass)
    else:
        template=template.replace("$desc",classname)
    # 文件名
    a=""
    if arr[0]!="":
        args=arr[0].split(",")
        for i in range(0,len(args)):
            args[i]=re.sub("\W","",args[i])
        a="_".join(args)
        a="_"+a
    saveName=funcName+a+".sublime-snippet"
    if classname==funcName:
        saveName="Class_"+saveName
    # print saveName
    # 建立类对应的目录
    newSaveDir=os.path.join(saveDir,classname)
    if childClass:
        newSaveDir=os.path.join(newSaveDir,childClass)
        # print(newSaveDir);
    if not os.path.exists(newSaveDir):
        os.makedirs(newSaveDir)
    savePath=os.path.join(newSaveDir,saveName)
    f=open(savePath, "w+")
    f.write(template)
    f.close()

# 处理属性,生成snippet文件
def handleProp(saveDir,classname,propName):
    # 以_开头的不记录
    if propName.find("_")==0:
        return
    template=snippetTemplate.replace("$content",propName)
    template=template.replace("$trigger",propName)
    template=template.replace("$desc",classname)
    # 文件名
    saveName=propName+".sublime-snippet"
    # print saveName
    # 建立类对应的目录
    saveDir=os.path.join(saveDir,classname)
    if not os.path.exists(saveDir):
        os.makedirs(saveDir)
    savePath=os.path.join(saveDir,saveName)
    f=open(savePath, "w+")
    f.write(template)
    f.close()

# 处理函数变量
def handleParams(params):
    args=[]
    for item in params.split(","):
        str1=re.sub("\W","",item)
        if str1!="":
            args.append(str1)
    args2=[]
    for i in range(0,len(args)):
        args2.append("${%d:%s}"%(i+1,args[i]))
    a1=", ".join(args)
    a2=", ".join(args2)
    return [a1,a2]


# 先删除保存目录下的文件，但不删除保存目录root
def deleteFiles(path,root):
    if os.path.isfile(path):
        try:
            os.remove(path)
        except Exception, e:
            pass
    elif os.path.isdir(path):
        for item in os.listdir(path):
            itemsrc=os.path.join(path,item)
            deleteFiles(itemsrc,root)
        if path!=root:
            try:
                os.rmdir(path)
            except Exception, e:
                pass

deleteFiles(SAVE_DIR,SAVE_DIR)
parse(srcPath)
# 保存声明文件
str1=json.dumps(definitionList)
datetime=time.strftime("%Y-%m-%d %X", time.localtime())
data=definitionTemplate.replace("$datetime",datetime)
data=data.replace("$json",str1)
f=open("definition.py","w+")
f.write(data)
f.close()
